{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 6. Inverse theory methods" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "%plot --format svg -s 800,600" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 6.1 Review of the least-squares fitting\n", "\n", "Linear regression that we used for the last project, was essentially a problem of minimizing the following sum of squares of residuals, i.e. the differences between the data $(x_i,y_i)$ and the linear model $y(x)=c_0+c_1 x$ predictions:\n", "$$\n", " \\min \\left[ \\sum_{i=1}^m r_i^2 \\right] , \\quad r_i = y_i - (c_0 + c_1 x_i)\n", "$$\n", "In matrix form, the problem is to solve the set of linear equations\n", "$$\n", " \\vec{y} = \\left( \\begin{array}{c} y_1 \\\\ y_2 \\\\ \\vdots \\\\ y_m\\end{array} \\right) =\n", " \\left( \\begin{array}{cc} 1 & x_1 \\\\ 1 & x_2 \\\\ \\vdots & \\dots \\\\ 1 & x_m\\end{array} \\right)\n", " \\left( \\begin{array}{c} c_0 \\\\ c_1 \\end{array} \\right)\n", "$$\n", "for $\\{ c_0,c_1\\}$. In octave this can be accomplished by using operator \\ :" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "c =\r\n", "\r\n", " -0.55333\r\n", " 0.98970\r\n", "\r\n" ] }, { "data": { "image/svg+xml": [ "\n", "\n", "Gnuplot\n", "Produced by GNUPLOT 5.2 patchlevel 0 \n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t \n", "\t \n", "\t\n", "\t\n", "\t \n", "\t \n", "\t\n", "\n", "\n", "\n", "\n", "\t\n", "\t\t\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t0\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t2\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t4\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t6\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t8\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t10\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t0\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t2\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t4\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t6\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t8\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t10\n", "\t\n", "\n", "\n", "\n", "\n", "\t\n", "\t\ty\n", "\t\n", "\n", "\n", "\t\n", "\t\tx\n", "\t\n", "\n", "\n", "\t\n", "\t\tLinear regression\n", "\t\n", "\n", "\n", "\n", "\n", "\t\n", "\tdata\n", "\n", "\n", "\n", "\t\n", "\t\tdata\n", "\t\n", "\n", "\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\n", "\t\n", "\tlinear regression\n", "\n", "\t\n", "\t\tlinear regression\n", "\t\n", "\n", "\n", "\t\t\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "x_data = [1:10]';\n", "y_data = [ 0.2 1.0 2.6 3.6 4.9 5.3 6.5 7.8 8.0 9.0 ]';\n", "A = [ ones(size(x_data)) x_data ];\n", "c = A \\ y_data\n", "\n", "y_lr = A*c;\n", "plot(x_data,y_data,'r.;data;',\n", " x_data,y_lr,'g-;linear regression;');\n", "ylabel('y');\n", "xlabel('x');\n", "legend(\"location\",'southeast');\n", "box on;\n", "grid on;\n", "title('Linear regression');" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There is another way to look at the solution of this overdetermined problem\n", "$$\n", " \\vec{y} = {A} \\vec{c}\n", "$$\n", "Any full rank matrix $A ∈ R^{m×n}$ , with $m \\geq n$, admits a unique $QR$ factorization\n", "$A = QR$. It is possible to prove that $A = \\tilde{Q}\\tilde{R}$ where $\\tilde{Q}=Q(1:m.1:n)$ and $\\tilde{R}=R(1:n,1:n)$ are the submatrices as showni below (figure from A.Quarteroni, F.Saleri and P.Gervasio, Scientific Computing with\n", "MATLAB and Octave, 3rd ed, Springer).\n", "

\n", "\"[Fig5.9]\"\n", "

\n", "$\\tilde{Q}$ has orthonormal column vectors, while $\\tilde{R}$ is a non-singular upper triangular matrix. Therefore, the unique solution is given by\n", "$$\n", " \\vec{c}^* = (\\tilde{R})^{-1} (\\tilde{Q})^T \\vec{y}\n", "$$" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ans =\n", "\n", " 1.00000 0.00000\n", " 0.00000 1.00000\n", "\n", "ans =\n", "\n", " 0 0\n", " 0 0\n", "\n", "ans =\n", "\n", " -0.55333 -0.55333\n", " 0.98970 0.98970\n", "\n" ] } ], "source": [ "### another view of the same linear regression problem: QR factorization\n", "### Again, solving A c = y for c by using A=QR\n", "[m,n] = size(A);\n", "### only works for an OVERdetermined system, m>n (here m=10, n=2)\n", "[Q,R] = qr(A);\n", "## \\tilde{Q} is an (mxn) subset of Q(mxm), \\tilde{R} is an (nxn) subset of R(mxn)\n", "Qt = Q(:,1:n); Rt = R(1:n,:);\n", "## \\tilde{Q} is an orthogonal matrix, so Qt`*Qt should be an identity:\n", "Qt'*Qt\n", "## R is already an upper-triungular matrix, so this should be identically zero:\n", "Rt - triu(Rt)\n", "## and this yields exactly the same result as before\n", "[c (Rt \\ (Qt'*y_data)) ]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But what if the task is not to minimize the (vertical) differences between $y_i$ and $c_0 + c_1 x_i$, but instead the sum of the distances between the data points and the line of fit? Another formulation of the problem is the \"minimum length of water pipes\" of an example distributed with eXtrema, see https://www.physics.brocku.ca/Labs/extrema/.\n", "\n", "On a plane, a straight line can be represented by the equation\n", "$$\n", " c_0 + c_1 x + c_2 y = 0, \\quad c_1^2 + c_2^2 = 1\n", "$$\n", "where $(c_1,c_2)$ is the unit vector perpendicular to the line. For points $(x_i,y_i)$ not on the line, the above equation represents the distances of the points from the line,\n", "$$\n", " r_i = c_0 + c_1 x_i + c_2 y_i \n", "$$\n", "and the problem becomes the minimization of the total sum of such distances:\n", "$$\n", " \\min ||\\vec{r} ||^2 = \\min \\left[ \\sum_{i=1}^m r_i^2 \\right]\n", "$$\n", "subject to\n", "$$\n", " \\vec{r} = \\left( \\begin{array}{c} r_1 \\\\ r_2 \\\\ \\vdots \\\\ r_m\\end{array} \\right) =\n", " \\left( \\begin{array}{ccc} 1 & x_1 & y_1 \\\\ 1 & x_2 & y_2 \\\\ \\vdots & \\dots & \\vdots\\\\ 1 & x_m & y_m\\end{array} \\right)\n", " \\left( \\begin{array}{c} c_0 \\\\ c_1 \\\\ c_2\\end{array} \\right) = A \\vec{c}\n", " \\quad \\mbox{and} \\quad\n", " c_1^2+c_2^2=1\n", "$$\n", "\n", "Commands \n", "qr(), \n", "triu(), and\n", "svd()\n", "will come handy." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ans =\r\n", "\r\n", " -0.41624 0.70565 -0.70856 1.00000 1.00000 1.00000\r\n", "\r\n" ] }, { "data": { "image/svg+xml": [ "\n", "\n", "Gnuplot\n", "Produced by GNUPLOT 5.2 patchlevel 0 \n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t \n", "\t \n", "\t\n", "\t\n", "\t \n", "\t \n", "\t\n", "\n", "\n", "\n", "\n", "\t\n", "\t\t\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t-4\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t-2\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t0\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t2\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t4\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t6\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t8\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t10\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t0\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t2\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t4\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t6\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t8\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\t\t\n", "\t\t10\n", "\t\n", "\n", "\n", "\n", "\n", "\t\n", "\t\ty\n", "\t\n", "\n", "\n", "\t\n", "\t\tx\n", "\t\n", "\n", "\n", "\t\n", "\t\tLeast-squares fitting: c = (-0.416, 0.706, -0.709)\n", "\t\n", "\n", "\n", "\n", "\n", "\t\n", "\tdata\n", "\n", "\n", "\n", "\t\n", "\t\tdata\n", "\t\n", "\n", "\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\n", "\t\n", "\tlinear regression\n", "\n", "\t\n", "\t\tlinear regression\n", "\t\n", "\n", "\n", "\t\t\n", "\n", "\n", "\t\n", "\tconstrained least squares\n", "\n", "\t\n", "\t\tconstrained least squares\n", "\t\n", "\n", "\n", "\t\t\n", "\n", "\n", "\t\n", "\t100 x difference\n", "\n", "\t\n", "\t\t100 x difference\n", "\t\n", "\n", "\n", "\t\t\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# this function solves the constrained least squares problem r = A c\n", "A = [ ones(size(x_data)) x_data y_data ];\n", "## m data, n parameters of the fit\n", "[m,n] = size(A);\n", "## on a two-dimensional plane, line normal only has two \n", "## components, (c_1,c_2), so only two parameters of the fit\n", "dim = 2; \n", "if n < dim+1, error ('not enough parameters'); end;\n", "if m < dim, error ('not enough data points'); end;\n", "\n", "## QR factorization\n", "[Q,R] = qr(A);\n", "## Singular value decomposition: V^T S* U = pseudoinverse of A\n", "[U,S,V] = svd(R(n-dim+1:m,n-dim+1:n)); \n", "cc = V(:,dim); ## only dim constraints are involved\n", "cc_0 = -R(1:n-dim,1:n-dim) \\ (R(1:n-dim,n-dim+1:n)*cc);\n", "\n", "[ [cc_0 cc'] (sqrt(cc(1)^2+cc(2)^2)) cc'*cc norm(cc)]\n", "\n", "y_ls = -(cc_0+cc(1)*x_data)/cc(2);\n", "plot(x_data,y_data,'r.;data;',\n", " x_data,y_lr,'g-;linear regression;',\n", " x_data,y_ls,'b-;constrained least squares;',\n", " x_data,100*(y_lr - y_ls),'c-;100 x difference;');\n", "ylabel('y');\n", "xlabel('x');\n", "legend(\"location\",'east');\n", "box on;\n", "grid on;\n", "title(sprintf('Least-squares fitting: c = (%.3f, %.3f, %.3f)',cc_0,cc(1),cc(2)));" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 6.2 Introduction to inverse problems" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "08_Sternin-reprint.pdf\t60C.dat expo_maketest.m\t pmma.eps test.dat\r\n", "30C.dat\t\t\t70C.dat expo_maketest.sci\t pmma.png\r\n", "40C.dat\t\t\t80C.dat expo.sci\t\t pmma.ps\r\n", "50C.dat\t\t\texpo.m\t inverse-theory-methods.pdf SS97.pdf\r\n" ] } ], "source": [ "%bash\n", "ls /work/5P10/Inverse/" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Inverse Theory presentation (pdf)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "Gnuplot\n", "Produced by GNUPLOT 5.2 patchlevel 0 \n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t \n", "\t \n", "\t\n", "\t\n", "\t \n", "\t \n", "\t\n", "\n", "\n", "\n", "\n", "\t\n", "\t\t\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0.1\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0.2\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0.3\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0.4\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0.5\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0.6\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0.7\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t10-5\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t10-4\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t10-3\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t10-2\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t10-1\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t100\n", "\t\n", "\n", "\n", "\n", "\n", "\t\n", "\t\tg(r)\n", "\t\n", "\n", "\n", "\t\n", "\t\tr\n", "\t\n", "\n", "\n", "\t\n", "\t\tTest distribution of relaxation rates\n", "\t\n", "\n", "\n", "\n", "\tgnuplot_plot_1a\n", "\n", "\n", "\n", "\t\n", "\t\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "Gnuplot\n", "Produced by GNUPLOT 5.2 patchlevel 0 \n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t \n", "\t \n", "\t\n", "\t\n", "\t \n", "\t \n", "\t\n", "\n", "\n", "\n", "\n", "\t\n", "\t\t\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t-0.2\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0.2\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0.4\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0.6\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0.8\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t1\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t20000\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t40000\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t60000\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t80000\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t100000\n", "\t\n", "\n", "\n", "\n", "\n", "\t\n", "\t\tf(t)\n", "\t\n", "\n", "\n", "\t\n", "\t\tt\n", "\t\n", "\n", "\n", "\t\n", "\t\tf(t) + 5.0% random noise, saved in noisy-0.05.dat\n", "\t\n", "\n", "\n", "\n", "\tgnuplot_plot_1a\n", "\n", "\n", "\n", "\t\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%% expo_maketest.m\n", "% make f(t) + noise, for testing TR analysis of \n", "% a distribution of relaxation rates, g(r) \n", "%\n", "% Completed: Dec.2005, Edward Sternin \n", "% Contributions: Hartmut Schaefer\n", "% Revisions: 2018.02 ES converted to matlab/octave from SciLab\n", "%\n", "clear;\n", "\n", "noise=0.05; % noise as fraction of the max(f(t))\n", "datafile=sprintf(\"noisy-%.2f.dat\",noise);\n", "\n", "t_steps=1000; % t-domain signal has this many points,\n", "t_min=1; % from this minimum,\n", "t_max=1e5; % to this maximum\n", "r_steps=500; % r-grid has this many points,\n", "r_min=1/t_max; % from this minimum,\n", "r_max=1/t_min; % to this maximum\n", "\n", "% Use an array of Gaussian peaks that make up the true g(r):\n", "%peaks = [[0.5 0.20 0.04];[0.65 0.50 0.03];[0.75 0.80 0.03]]; % [amplitude center width]\n", "peaks = [[0.5 0.20 0.04];[0.65 0.50 0.03]]; % [amplitude center width]\n", "%peaks = [[0.6 0.35 0.1];[0.1 0.45 0.15]]; % [amplitude center width]\n", "\n", "% create a vector of r values, logarithmically spaced\n", "r_scale = log(r_max)-log(r_min);\n", "r = exp([log(r_min):r_scale/(r_steps-1):log(r_max)])'; % use a column vector\n", "\n", "% build up g(r) by adding Gaussian contributions from all peaks\n", "g = zeros(length(r),1);\n", "for k=1:length(peaks(:,1))\n", " r0 = log(r_min) + r_scale*peaks(k,2);\n", " dr = r_scale*peaks(k,3);\n", " g += peaks(k,1) * exp (- (log(r) - r0).^2 / (2 * dr^2));\n", "end\n", "\n", "f1=figure(1); clf(1);\n", "semilogx(r,g,'r-','LineWidth',2);\n", "ylabel(\"g(r)\");\n", "xlabel(\"r\");\n", "title(\"Test distribution of relaxation rates\");\n", "FS = findall(f1,'-property','FontSize');\n", "set(FS,'FontSize',14);\n", "%print -dpng g.png\n", "\n", "% create a vector of t values, linearly spaced; use column vectors for f(t)\n", "t = [t_min:(t_max-t_min)/(t_steps-1):t_max]';\n", "\n", "% generate time-domain data\n", "f = (1/(length(t)-1)*g'*exp(-r*t'))';\n", "\n", "% normalize and add random noise\n", "f /= max(f);\n", "f += noise*(-0.5+rand(length(f),1));\n", "\n", "f2=figure(2); clf(2);\n", "plot(t,f,'g-');\n", "%semilogy(t,f,'g-');\n", "ylabel(\"f(t)\");\n", "xlabel(\"t\");\n", "title(sprintf(\"f(t) + %.1f%% random noise, saved in %s\",100*noise,datafile));\n", "FS = findall(f2,'-property','FontSize');\n", "set(FS,'FontSize',14);\n", "%print -dpng f.png\n", "\n", "%system(sprintf(\"rm -rf %s\",datafile));\n", "f_of_t=[t f];\n", "save(\"-ascii\",datafile,\"f_of_t\");\n", "\n", "g_of_r=[r g];\n", "save(\"-ascii\",\"true_g.dat\",\"g_of_r\");\n" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "Gnuplot\n", "Produced by GNUPLOT 5.2 patchlevel 0 \n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t \n", "\t \n", "\t\n", "\t\n", "\t \n", "\t \n", "\t\n", "\n", "\n", "\n", "\n", "\t\n", "\t\t\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t-0.2\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0.2\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0.4\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0.6\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0.8\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t1\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t20000\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t40000\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t60000\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t80000\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t100000\n", "\t\n", "\n", "\n", "\n", "\n", "\t\n", "\t\tf(t)\n", "\t\n", "\n", "\n", "\t\n", "\t\tt\n", "\t\n", "\n", "\n", "\t\n", "\t\tLS error norm = 0.000202\n", "\t\n", "\n", "\n", "\n", "\n", "\t\n", "\tinput data, f(t)\n", "\n", "\n", "\n", "\t\n", "\t\tinput data, f(t)\n", "\t\n", "\n", "\n", "\t\t\n", "\n", "\n", "\t\n", "\tmisfit, x7.43\n", "\n", "\t\n", "\t\tmisfit, x7.43\n", "\t\n", "\n", "\n", "\t\t\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "Gnuplot\n", "Produced by GNUPLOT 5.2 patchlevel 0 \n", "\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t \n", "\t \n", "\t\n", "\t\n", "\t \n", "\t \n", "\t\n", "\n", "\n", "\n", "\n", "\t\n", "\t\t\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0.2\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0.4\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0.6\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t0.8\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t10-6\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t10-5\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t10-4\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t10-3\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t10-2\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t10-1\n", "\t\n", "\n", "\n", "\t\t\n", "\t\t100\n", "\t\n", "\n", "\n", "\n", "\n", "\t\n", "\t\tg(r)\n", "\t\n", "\n", "\n", "\t\n", "\t\tr\n", "\t\n", "\n", "\n", "\t\n", "\t\tPseudo-inverse solution\n", "\t\n", "\n", "\n", "\n", "\n", "\t\n", "\ttrue g(r)\n", "\n", "\n", "\n", "\t\n", "\t\ttrue g(r)\n", "\t\n", "\n", "\n", "\t\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\n", "\t\n", "\tnoisy-0.05.dat, SVD=0, l=0.007\n", "\n", "\t\n", "\t\tnoisy-0.05.dat, SVD=0, l=0.007\n", "\t\n", "\n", "\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\t\n", "\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "\t\n", "\n", "\n", "\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%% expo.m\n", "% multi-exponential inverse analysis of time decay curves\n", "% f(t) = \\int g(r) exp(-r*t) dr\n", "%\n", "% Notation:\n", "% r = vector or r values\n", "% n = number of points in r\n", "% g = vector of unknowns, g(r)\n", "% t = vector of t values\n", "% m = number of points in t\n", "% f = vector of measured data, f(t)\n", "% K = (m x n) kernel matrix\n", "% svd_cnt = keep only this many singular values\n", "% lambda = Tikhonov regularization parameter\n", "% datafile = (noisy) data, in two columns: (t,f)\n", "%\n", "% Completed: Dec.2005, Edward Sternin \n", "% Contributions: Hartmut Schaefer\n", "% Revisions: 2018.02 ES converted to matlab/octave from SciLab\n", "%\n", "\n", "clear;\n", "\n", "function [g] = regularize(t,f,r,K,svd_n,lambda)\n", " m=length(f);\n", " n=length(r);\n", " if (m < n) \n", " error (\"This code is not meant for underdetermined problems, need more data\");\n", " end\n", "\n", " % SVD of the kernel matrix\n", " [U,S,V]=svd(K);\n", "\n", " nt=n;\n", " % if requested, truncate the number of singular values\n", " if (svd_n > 0)\n", " nt=min(n,svd_n);\n", " nt=max(nt,2); % but not too few!\n", " end\n", "\n", " % Tikhonov regularization\n", " sl=S(nt,nt);\n", " for k=1:nt \n", " sl(k,k)=S(k,k)/(S(k,k)^2+lambda);\n", " end\n", "\n", " % return g(r)\n", " g=V(1:n,1:nt)*sl*U(1:m,1:nt)'*f; \n", " \n", "end\n", "\n", "%====================================================\n", "\n", "datafile='noisy-0.05.dat';\n", "r_steps=70; % r-grid has this many points,\n", "r_min=1e-6; % from this minimum,\n", "r_max=1; % to this maximum\n", "svd_cnt=0; % set to 0 for no SVD truncation`\n", "lambda=7e-3; % set to 0 for no Tikhonov regularization\n", "\n", "% read in the time-domain data\n", "f_of_t=dlmread(datafile);\n", "t=f_of_t(:,1); % first column is time\n", "f=f_of_t(:,2); % second column is f(t)\n", "\n", "% create a vector of r values, logarithmically spaced\n", "r_inc = (log(r_max)-log(r_min)) / (r_steps-1);\n", "r = exp([log(r_min):r_inc:log(r_max)]);\n", "\n", "% set up our kernel matrix, normalize by the step in r\n", "K = exp(-t*r) * r_inc;\n", "\n", "% call the inversion routine\n", "[g] = regularize(t,f,r,K,svd_cnt,lambda);\n", "\n", "% plot the original data f(t) and our misfit\n", "f1=figure(1); clf(1);\n", "hold on;\n", "plot(t,f,'-'); \n", "\n", "misfit = f - K*g ;\n", "Psi = sum(misfit.^2)/(length(f)-1);\n", "scale=0.2*max(f)/max(misfit);\n", "plot(t,scale*misfit,'-r');\n", "\n", "title(sprintf(\"LS error norm = %f\",Psi));\n", "xlabel(\"t\");\n", "ylabel(\"f(t)\");\n", "legend(\"input data, f(t)\",sprintf(\"misfit, x%.2f\",scale));\n", "FS = findall(f1,'-property','FontSize');\n", "set(FS,'FontSize',14);\n", "hold off;\n", "\n", "% separately, plot the result of the inversion\n", "f2=figure(2); clf(2);\n", "hold on;\n", "\n", "g_of_r=dlmread(\"true_g.dat\");\n", "r_true=g_of_r(:,1);\n", "g_true=g_of_r(:,2);\n", "r_inc_true=(log(max(r_true))-log(min(r_true)))/(length(r_true)-1);\n", "semilogx(r_true,g_true/(sum(g_true)*r_inc_true),'b:o','MarkerSize',0.5);\n", "\n", "semilogx(r,g/(sum(g)*r_inc),'r.','MarkerSize',3);\n", "title(\"Pseudo-inverse solution\");\n", "xlabel(\"r\");\n", "ylabel(\"g(r)\");\n", "legend(\"true g(r)\",sprintf(\"%s, SVD=%d, \\\\lambda=%.2g\",datafile,svd_cnt,lambda));\n", "FS = findall(f2,'-property','FontSize');\n", "set(FS,'FontSize',14);\n", "ylim([-0.1 0.9]) % last-minute tweak, to avoid the legend\n", "hold off;\n", "\n", "%print -depsc result.eps" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 6.3 Homework, due 2022-11-14\n", "\n", "

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\"[pmma.png]\"" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "/work/5P10/Inverse/30C.dat /work/5P10/Inverse/60C.dat\r\n", "/work/5P10/Inverse/40C.dat /work/5P10/Inverse/70C.dat\r\n", "/work/5P10/Inverse/50C.dat /work/5P10/Inverse/80C.dat\r\n" ] } ], "source": [ "%bash\n", "ls /work/5P10/Inverse/*C.dat" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Octave", "language": "octave", "name": "octave" }, "language_info": { "file_extension": ".m", "help_links": [ { "text": "GNU Octave", "url": "https://www.gnu.org/software/octave/support.html" }, { "text": "Octave Kernel", "url": "https://github.com/Calysto/octave_kernel" }, { "text": "MetaKernel Magics", "url": "https://metakernel.readthedocs.io/en/latest/source/README.html" } ], "mimetype": "text/x-octave", "name": "octave", "version": "4.2.2" } }, "nbformat": 4, "nbformat_minor": 2 }